/*
    The MIT License

    Copyright (c) 2010 IFMO/GameDev Studio

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
*/

#pragma once


typedef HardRef<class IRenderSystem	>	IPxRenderSystem		;
typedef HardRef<class IUIScene		>	IPxUIScene			;

typedef HardRef<class IDVScene		>	IPxDVScene			;	

typedef HardRef<class IFRScene		>	IPxFRScene			;
typedef HardRef<class IFREntity		>	IPxFREntity			;
typedef HardRef<class IFRLight		>	IPxFRLight			;
typedef HardRef<class IFRGFX		>	IPxFRGFX			;
typedef HardRef<class IFRShader		>	IPxFRShader			;
typedef HardRef<class IFRVolume		>	IPxFRVolume			;

/*-----------------------------------------------------------------------------
	Enumerations :
-----------------------------------------------------------------------------*/

enum ERSGFXBlend {
		RS_GFX_NORMAL,
		RS_GFX_ADDITIVE,
		RS_GFX_SUBTRACTIVE,
		RS_GFX_MULTIPLY,
		RS_GFX_LIGHTEN,
		RS_GFX_DISTORTIVE,
	};

/*-----------------------------------------------------------------------------
	Structures :
-----------------------------------------------------------------------------*/

struct ERSQuad_s {
		ETexCoord	p0;
		ETexCoord	p1;
		ETexCoord	uv0;
		ETexCoord	uv1;
		EColor		color;
	};

struct ERSLine_s {
		EPoint		v0; 
		EColor		c0;
		ETexCoord	uv0;
		
		EPoint		v1;
		EColor		c1;
		ETexCoord	uv1;
	};
	
struct ERSVert2D_s {
		EColor		color;
		ETexCoord	p;
		ETexCoord	uv;
	};
	

/*-----------------------------------------------------------------------------
	Drawing stuff :
-----------------------------------------------------------------------------*/

struct EUIQuad;

class IUIScene : public ICoreObject {
	public:
		virtual void		ReloadShaders		( void ) = 0;	//	TODO : move to derived class
		virtual void		Set2DViewMode		( float offset_x=0, float offset_y=0 ) = 0;
		virtual void		SetColorMultiplier	( const EColor &color ) = 0;
		virtual	void		RenderQuads			( uint num_quads, const EUIQuad *quads, const EString image ) = 0;
		virtual void		GetImageSize		( const EString &image, uint &w, uint &h ) = 0;
	};

/*-----------------------------------------------------------------------------
	Debug visualization scene :
-----------------------------------------------------------------------------*/

class IDVScene : public ICoreObject {
	public:
		virtual void		ReloadShaders	( void ) = 0;	//	TODO : move to derived class
		virtual void		SetView			( const EPoint &position, const EQuaternion &orient ) = 0;
		virtual void		SetProjection	( float znear, float zfar, float width, float height ) = 0;
		virtual void		DrawLine		( const ERSLine_s &line ) = 0;
		virtual void		RenderScene		( void ) = 0;	//	TODO : move to derived class
		
		virtual void		DrawPoint		( const EPoint &origin, float size, const EColor &color ) = 0; 
		virtual void		DrawArrow		( const EPoint &origin, const EVector &dir, float scale, const EColor &color ) = 0; 
		virtual void		DrawBox			( const EBBox &bbox, const EColor &color ) = 0;

		virtual void		PushWorldMatrix	( void ) = 0;
		virtual void		MulWorldMatrix	( const EMatrix world ) = 0;
		virtual void		MulWorldMatrix	( const EPoint &position, const EQuaternion &orient ) = 0;
		virtual void		PopWorldMatrix	( void ) = 0;
	};


/*-----------------------------------------------------------------------------
	Forward shading scene :
-----------------------------------------------------------------------------*/

enum ERSEntityFlags {
		RSE_HIDDEN	=	0x0001,
	};
	
enum ERSLightType {
		RS_LIGHT_OMNI,
		RS_LIGHT_SPOT_SHADOW,
		RS_LIGHT_DIRECT_SHADOW,
	};	
	
class IFRScene : public ICoreObject {
	public:
		virtual void		SetGlobalFXTime	( float seconds ) = 0;
		virtual float		GetGlobalFXTIme	( void ) const = 0;

		virtual void		ReloadShaders	( void ) = 0;	//	TODO : move to derived class
		virtual void		ReloadResources	( void ) = 0;	//	TODO : move to derived class
		virtual void		RenderScene		( void ) = 0;	//	TODO : move to derived class

		virtual void		SetView			( const EPoint &position, const EQuaternion &orient ) = 0;
		virtual void		SetProjection	( float znear, float zfar, float width, float height ) = 0;
		
		virtual IPxFREntity	AddEntity		( void ) = 0;
		virtual IPxFRLight	AddLight		( void ) = 0;
		virtual IPxFRGFX	AddGFX			( void ) = 0;

		virtual void		SetAmbientLevel	( const EColor &ambient_level ) = 0;
		
		virtual void		GetViewProj		( EFrustum &view_frustum, EPoint &view_pos, EQuaternion &view_orient ) = 0;
		
		virtual void		AddWater		( const EString &mesh, const EString &noise, float omega, float scale, float falloff ) = 0;
		
		virtual void		SetWaterTime		( float time ) = 0;
		virtual void		RemoveWater			( void ) = 0;
		virtual void		GetWaterDynamics	( const EPoint &pos, float &pressure, float &surface_level, EVector &velocity ) = 0;
		virtual void		MakeWaterDrop		( const EPoint &pos, float offset ) = 0;

		virtual	IPxFRVolume	AddVolume		( void ) = 0;
		virtual void		RemoveVolume	( void ) = 0;
};


class IFREntity : public ICoreObject {
	public:
		virtual void		Render			( void ) = 0;	//	TODO : move to derived class
		virtual void		Reload			( void ) = 0;	//	TODO : move to derived class
		virtual void		SetPose			( const EPoint &position, const EQuaternion &orient ) = 0;
		virtual void		SetMesh			( const IPxTriMesh mesh, bool update_verts_only=false ) = 0;
		virtual void		SetColor		( const EColor &color ) = 0;
		virtual void		SetTime			( float time ) = 0;
		virtual uint		GetFlag			( void ) const = 0;
		virtual void		SetFlag			( uint flags ) = 0;
		virtual void		SetJointXForm	( uint joint_id, const EMatrix &xform ) = 0;
	};

class IFRVolume : public ICoreObject {
	public:
		class DataProvider {
		public:
			virtual float Value( const EPoint &local_point ) const = 0;

			virtual ~DataProvider() {}
		};
		virtual void		UpdateData		( const DataProvider *provider ) = 0;

		virtual void		Reload			( void ) = 0;	//	TODO : move to derived class
		virtual void		SetPose			( const EPoint &position, const EQuaternion &orient ) = 0;
 
		virtual void		LoadFromCube	( const EString &path ) = 0;
		virtual void		LoadFromRAW		( const EString &path, int w, int h, int d ) = 0;
		virtual	void		LoadColormap	( const EString &path ) = 0;

		virtual	void		SetBounds		( const EBBox &box) = 0;
		virtual void		SetResolution	( uint res_x, uint res_y, uint res_z ) = 0;
		virtual	void		SetColormap		( int n, const EColor *colors ) = 0;
		virtual void		SetInterestRange( float lo, float hi ) = 0;

	};
	

class IFRLight : public ICoreObject {
	public:
		virtual void		SetEnable		( bool enable=false ) = 0;
		virtual void		SetPose			( const EPoint &position, const EQuaternion &orient ) = 0;
		virtual void		SetColor		( const EColor &color ) = 0;
		virtual void		SetRadius		( float radius=1, float spot_radius=1 ) = 0;
		virtual void		SetType			( ERSLightType light_type ) = 0;
		virtual void		SetMask			( const EString &mask ) = 0;
	};	
	

class IFRGFX : public ICoreObject {
	public:
		virtual void	AllocSprites	( uint num ) = 0;
		virtual void	SetTexture		( const EString &texname, ERSGFXBlend blend ) = 0;
		virtual void	SetColor		( uint sprite_id, const EColor &color ) = 0;
		virtual void	SetVertices		( uint sprite_id, const EPoint *vertices, const ETexCoord *uvs0, const ETexCoord *uvs2 ) = 0;
		virtual void	AimToCamera		( uint sprite_id, const EPoint &origin, float size, float angle, float aspect ) = 0;
		virtual void	SetCrossFade	( uint sprite_id, float xfade ) = 0;
		virtual void	SetVisible		( uint sprite_id, bool visible ) = 0;
	};

/*-----------------------------------------------------------------------------
	Deferred shading scene :
-----------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------
	IRenderSystem
-----------------------------------------------------------------------------*/


class	IRenderSystem : public ICoreObject {
	public:
		virtual void		Install				( void ) = 0;
		virtual void		Uninstall			( void ) = 0;
	
		virtual	bool		BeginFrame			( void ) = 0;
		virtual void		RenderFrame			( void ) = 0;
		virtual void		EndFrame			( void ) = 0;
		
		virtual IPxFRScene	GetFRScene			( void ) = 0;
		virtual IPxDVScene	GetDVScene			( void ) = 0;
		virtual IPxUIScene	GetUIScene			( void ) = 0;

		virtual void		GetScreenSize		( uint &w, uint &h ) = 0;
		virtual void *		GetWindowHandle		( void ) = 0;
	};

